﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ICSharpCode.TextEditor.Document
{
    public class JavaFoldingStrategy : IFoldingStrategy
    {
        public JavaFoldingStrategy()
        {

        }

        #region IFoldingStrategy

        /// <summary>
        /// Adds folds to the text editor around each start-end element pair.
        /// </summary>
        /// <remarks>
        /// <param>If the xml is not well formed then no folds are created.</param> 
        /// <para>Note that the xml text reader lines and positions start 		 
        /// </remarks>
        public List<FoldMarker> GenerateFoldMarkers(IDocument document, string fileName, object parseInformation)
        {
            return GenerateFoldMarkers(document);
        }

        /// <summary>
        /// Adds folds to the text editor around each start-end element pair.
        /// </summary>
        /// <param name="document"></param>
        /// <returns></returns>
        public List<FoldMarker> GenerateFoldMarkers(IDocument document)
        {
            List<FoldMarker> foldMarkers = new List<FoldMarker>();
            //需要分开
            int start = 0;
            //stack 先进先出
            var startLines = new Stack<int>();
            var startTextLines = new Stack<string>();

            int start_script = 0;
            var start_Script_Lines = new Stack<int>();
            var start_Script_TextLines = new Stack<string>();

            int import_end_line = 0;
            var import_start = false;
            var import_start_label = "";

            var comment_start = false;
            var comment_start_label = "";

            // Create foldmarkers for the whole document, enumerate through every line.
            for (int i = 0; i < document.TotalNumberOfLines; i++)
            {

                char c;
                int offs, end = document.TextLength;
                LineSegment seg = document.GetLineSegment(i);

                for (offs = seg.Offset; offs < end && ((c = document.GetCharAt(offs)) == ' ' || c == '\t'); offs++)
                {
                    //offs 增加
                }
                if (offs == end)
                    break;
                int spaceCount = offs - seg.Offset;

                // Get the text of current line.
                string text = document.GetText(document.GetLineSegment(i));

                //import               
                if (text.Trim().StartsWith("import", StringComparison.OrdinalIgnoreCase))
                {
                    if(!import_start)
                    {
                        startLines.Push(i);
                        import_start = true;
                        import_start_label = text;
                    }                   
                    import_end_line = i;
                    startTextLines.Push(text);
                }
                if (import_start && !string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text.Trim()))
                {
                    if (!text.Trim().StartsWith("import", StringComparison.OrdinalIgnoreCase))
                    {
                        start = startLines.Pop();
                        string regionLabel = startTextLines.Pop();
                        string regionText = "import ...";
                        foldMarkers.Add(new FoldMarker(document, start, document.GetLineSegment(start).Length - import_start_label.Length, import_end_line, spaceCount + import_start_label.Length + regionLabel.Length + regionText.Length, FoldType.Unspecified, regionText));

                        import_start = false;
                    }
                }

                // /**  */               
                if (text.Trim().StartsWith("/**", StringComparison.OrdinalIgnoreCase)) // Look for method starts
                {
                    startLines.Push(i);
                    startTextLines.Push(text);
                    comment_start = true;
                }
                if (comment_start && text.Trim().StartsWith("*", StringComparison.OrdinalIgnoreCase))
                {
                    if (string.IsNullOrEmpty(comment_start_label) && !string.IsNullOrEmpty(text.Replace('*', ' ').Trim()))
                    {
                        comment_start_label = text.Replace('*',' ').Trim();
                    }
                }
                if (text.Trim().StartsWith("*/", StringComparison.OrdinalIgnoreCase)) // Look for method endings
                {
                    if (startLines.Count > 0)
                    {
                        start = startLines.Pop();
                        string regionLabel = startTextLines.Pop();
                        string regionText = comment_start_label + "...";
                        foldMarkers.Add(new FoldMarker(document, start, document.GetLineSegment(start).Length - regionLabel.TrimStart().Length, i, spaceCount + regionLabel.Length + text.Length + "//".Length, FoldType.Unspecified, regionText));
                    }
                    comment_start_label = "";
                    comment_start = false;
                }                

                // { ... }
                if (text.Trim().StartsWith("{") || text.Trim().EndsWith("{")) // Look for method starts
                    if (text.Trim().StartsWith("{") || (text.Trim().IndexOf("}") == -1 && text.Trim().EndsWith("{"))) // Look for method starts
                    {
                        start_Script_Lines.Push(i);
                    }
                if (text.Trim().StartsWith("}")) // Look for method endings
                {
                    if (start_Script_Lines.Count > 0)
                    {
                        int start0 = start_Script_Lines.Pop();
                        foldMarkers.Add(new FoldMarker(document, start0, document.GetLineSegment(start0).Length - "{".Length, i, 57, FoldType.TypeBody, "{...}"));
                    }
                }

            }

            return foldMarkers;
        }

        #endregion

    }
}
